package com.geniusk.app.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.GifCaptcha;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.geniusk.common.config.IoTConfig;
import com.geniusk.common.constant.CaptchaConstants;
import com.geniusk.common.constant.RedisConstants;
import com.geniusk.common.core.JSONResult;
import com.geniusk.common.utils.IpUtil;
import com.geniusk.common.utils.RedisUtil;
import com.geniusk.common.utils.ServletUtil;
import com.geniusk.common.utils.SmsUtil;
import com.geniusk.security.enums.LoginSourceType;
import com.geniusk.security.utils.SecurityUtil;
import com.geniusk.security.utils.TokenUtil;
import com.geniusk.system.model.bo.passport.LoginBO;
import com.geniusk.system.model.bo.passport.MobileBO;
import com.geniusk.system.model.bo.passport.RegisterAndLoginBO;
import com.geniusk.system.model.pojo.User;
import com.geniusk.system.service.MenuService;
import com.geniusk.system.service.UserService;
import com.geniusk.system.utils.LoginUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * APP登录验证接口
 */
@RestController
@RequestMapping("/app/passport")
public class AppPassportController {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserService userService;

    @Autowired
    private SmsUtil smsUtil;

    @Autowired
    private LoginUtil loginUtil;

    @Autowired
    private MenuService menuService;

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private IoTConfig ioTConfig;

    /**
     * 获取图片验证码
     */
    @GetMapping("/getCheckImage")
    public JSONResult getCheckImage() {
        Map<String, Object> result = new HashMap<>();
        //生成uuid
        String checkId = IdUtil.fastUUID();
        String captchaType = ioTConfig.getCaptchaType();
        //生成验证码
        if(captchaType.equals(CaptchaConstants.MATH_CHAR)){
            LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 45, 4, 10);
            result.put("checkId", checkId);
            //获取验证码的base64
            result.put("checkImg", lineCaptcha.getImageBase64Data());
            result.put("useCheckImage", CaptchaConstants.TRUE.equals(ioTConfig.getCaptchaEnabled()));
            //获取验证码内容
            String checkData = lineCaptcha.getCode();
            redisUtil.setCacheObject(getCheckId(checkId), checkData, 60, TimeUnit.SECONDS);
        }else {
            GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(200, 45,4);
            result.put("checkId", checkId);
            //获取验证码的base64
            result.put("checkImg", gifCaptcha.getImageBase64Data());
            result.put("useCheckImage", CaptchaConstants.TRUE.equals(ioTConfig.getCaptchaEnabled()));
            //获取验证码内容
            String checkData = gifCaptcha.getCode();
            redisUtil.setCacheObject(getCheckId(checkId), checkData, 60, TimeUnit.SECONDS);
        }

        return JSONResult.ok(result);
    }

    /**
     * 用户登陆
     */
    @PostMapping("/login")
    public JSONResult login(@Valid @RequestBody LoginBO loginBO) {
        if(CaptchaConstants.TRUE.equals(ioTConfig.getCaptchaEnabled())){
            //校验验证码
            String checkId = getCheckId(loginBO.getCheckId());
            Boolean hasKey = redisUtil.hasKey(checkId);
            //判断key是否存在，不存在返回失效
            if (hasKey == null || !hasKey) {
                return JSONResult.errorMsg("验证码失效，请刷新验证码");
            }
            //验证内容是否相同
            String checkData = redisUtil.getCacheObject(checkId);
            String checkCode = loginBO.getCheckCode();
            if (!StrUtil.equalsIgnoreCase(checkData, checkCode)){
                return JSONResult.errorMsg("验证码错误");
            }
            redisUtil.deleteObject(checkId);
        }
        String token = loginUtil.getLoginToken(loginBO.getUsername(),loginBO.getPassword(), LoginSourceType.ANDROID_LOGIN);
        return JSONResult.loginSucceed(token);
    }

    /**
     * 获取手机验证码
     * @param mobileBO 手机号
     * @return 获取结果
     */
    @PostMapping("/getSmsCode")
    public JSONResult getSmsCode(@Valid @RequestBody MobileBO mobileBO){
        String phoneNumber = mobileBO.getPhoneNumber();
        String ip = IpUtil.getIpAddr(ServletUtil.getRequest());
        boolean absent = redisUtil.setCacheObjectIfAbsent(getSmsIpKey(ip), phoneNumber, 5*60, TimeUnit.SECONDS);
        if(absent){
            String code = RandomUtil.randomNumbers(6);
            smsUtil.sendSMS(phoneNumber,code);
            redisUtil.setCacheObject(getSmsCodeKey(phoneNumber), code, 5 * 60,TimeUnit.SECONDS);
        }else{
            return JSONResult.errorMsg("请勿重复发送验证码");
        }
        return JSONResult.ok();
    }

    /**
     * 用户注册登陆
     * @param registerAndLoginBO 注册登陆
     * @return 登陆结果
     */
    @PostMapping("/registerAndLogin")
    public JSONResult registerAndLogin(@Valid @RequestBody RegisterAndLoginBO registerAndLoginBO){
        String phoneNumber = registerAndLoginBO.getPhoneNumber();
        String smsCode = registerAndLoginBO.getSmsCode();
        String smsCodeKey = getSmsCodeKey(phoneNumber);
        // 从redis中获得验证码进行校验判断是否匹配
        String redisCode = redisUtil.getCacheObject(smsCodeKey);
        if (StrUtil.isBlank(redisCode) || !redisCode.equalsIgnoreCase(smsCode)) {
            return JSONResult.errorMsg("验证码不正确");
        }
        // 用户登录注册以后，删除redis中的短信验证码
        redisUtil.deleteObject(smsCodeKey);
        String token = loginUtil.getLoginToken(phoneNumber);
        return JSONResult.loginSucceed(token);
    }

    /**
     * 获取用户信息
     */
    @GetMapping("getUserInfo")
    public JSONResult getUserInfo() {
        User user = userService.selectUserById(SecurityUtil.getUserId());
        // 权限集合
        Set<String> funcPermissions = menuService.selectPermissionByUserId(SecurityUtil.getUserId());
        Map<String,Object> result = new HashMap<>();
        result.put("user",user);
        result.put("permissions", funcPermissions);
        return JSONResult.ok(result);
    }

    /**
     * 退出登录
     * @return 退出结果
     */
    @DeleteMapping("/logout")
    public JSONResult logout() {
        try {
            Long identityId = SecurityUtil.getLoginUser().getIdentityId();
            tokenUtil.delLoginUserByIdentityId(identityId);
        }catch (Exception e){
            return JSONResult.ok("退出成功");
        }
        return JSONResult.ok("退出成功");
    }

    /**
     * 获取手机验证码IPKey
     * @param ip ip地址
     * @return 手机验证码IPKey
     */
    private String getSmsIpKey(String ip){
        return RedisConstants.MOBILE_SMS_IP + ip;
    }

    /**
     * 获取手机验证码Key
     * @return 手机验证码Key
     */
    private String getSmsCodeKey(String phoneNumber){
        return RedisConstants.MOBILE_SMS_CODE + phoneNumber;
    }

    /**
     * 添加redis key前缀
     * @param uuid 验证码id
     * @return redis key
     */
    private String getCheckId(String uuid) {
        return RedisConstants.LOGIN_CHECK_ID + uuid;
    }
}
